/*
 * IDDataCollection.h
 *
 *  Created on: Jul 9, 2011
 *      Author: matthew
 */

#ifndef IDDATACOLLECTION_H_
#define IDDATACOLLECTION_H_

#include <vector>
#include <string>
#include <stdio.h>

#include "IDData.h"

using namespace std;

template<class T> class CIDDataCollection{
		vector<CIDData<T> > *pIDData;
	public:
		CIDDataCollection();
		CIDDataCollection(CIDDataCollection<T> const &);
		CIDDataCollection& operator=(CIDDataCollection<T> const &);
		~CIDDataCollection();

		void AddData(string, float, vector<T>);
		unsigned int GetNumIDs();
		int GetNumDataEntriesForID(string);
		int GetNumDataEntriesForIndex(unsigned int);
		string GetIDOfIndex(unsigned int);
		int GetIndexOfID(string);
		float GetTimestamp(string, unsigned int);
		float GetTimestamp(unsigned int, unsigned int);
		void SetTimestamp(unsigned int, unsigned int, float);
		void SetTimestamp(string, unsigned int, float);
		vector<T> GetData(string, unsigned int);
		vector<T> GetData(unsigned int, unsigned int);
		string GetID(unsigned int);
};

// Return the index of the CIDData object with an ID string that matches strID
// Return -1 if no match is found
template<class T> int CIDDataCollection<T>::GetIndexOfID(string strID){
	for (unsigned int nCounter = 0; nCounter < pIDData->size(); nCounter++){
		if (pIDData->at(nCounter).GetID().compare(strID) == 0)
			return nCounter;
	}
	return -1;
}

// Default constructor
template<class T> CIDDataCollection<T>::CIDDataCollection(){
	pIDData = new vector<CIDData<T> >;
}

template<class T> CIDDataCollection<T>::CIDDataCollection(CIDDataCollection const &rhs){
	pIDData = new vector<CIDData<T> > (*(rhs.pIDData));
}

template<class T> CIDDataCollection<T>& CIDDataCollection<T>::operator=(CIDDataCollection const &rhs){
	if (this != &rhs){
		delete pIDData;
		pIDData = new vector<CIDData<T> > (*(rhs.pIDData));
	}
	return *this;
}

// Desctructor
template<class T> CIDDataCollection<T>::~CIDDataCollection(){
	delete pIDData;
}

// Add data with time-stamp to the CIDData object with matching ID string
// Create new CIDData object if none with matching ID found
template<class T> void CIDDataCollection<T>::AddData(string strID, float fTime, vector<T> data){
	int nIndex = this->GetIndexOfID(strID);
	if (nIndex == -1)
	{
		CIDData<T> temp(strID, fTime, data);
		pIDData->push_back(temp);
	}
	else
	{
		pIDData->at(nIndex).AddData(fTime, data);
	}
}

template<class T> unsigned int CIDDataCollection<T>::GetNumIDs(){
	return pIDData->size();
}

template<class T> int CIDDataCollection<T>::GetNumDataEntriesForIndex(unsigned int nIndex){
	if (nIndex < pIDData->size())
		return pIDData->at(nIndex).GetNumOfDataPayloads();
	else
		return -1;
}

template<class T> string CIDDataCollection<T>::GetIDOfIndex(unsigned int nIndex){
	if (nIndex < pIDData->size())
		return pIDData->at(nIndex).GetID();
	else
		return "";
}

template<class T> float CIDDataCollection<T>::GetTimestamp(string strID, unsigned int nIDDataIndex){
	int nIDIndex = this->GetIndexOfID(strID);
	if (nIDIndex == -1)
		return 0.0;
	else
	{
		if (nIDDataIndex >= pIDData->at(nIDIndex).GetNumOfDataPayloads())
			return 0.0;
		else
			return pIDData->at(nIDIndex).GetTimestamp(nIDDataIndex);
	}
}

template<class T> float CIDDataCollection<T>::GetTimestamp(unsigned int nIDIndex, unsigned int nIDDataIndex){
	if (nIDIndex >= pIDData->size())
		return 0.0;
	else if (nIDDataIndex >= pIDData->at(nIDIndex).GetNumOfDataPayloads())
		return 0.0;
	else
		return pIDData->at(nIDIndex).GetTimestamp(nIDDataIndex);
}

template<class T> void CIDDataCollection<T>::SetTimestamp(unsigned int nIDIndex, unsigned int nElementIndex, float fTime){
	if (nIDIndex < pIDData->size())
	{
		if (nElementIndex < pIDData->at(nIDIndex).GetNumOfDataPayloads())
		{
			pIDData->at(nIDIndex).SetTimestamp(nElementIndex, fTime);
		}
		else
			return;
	}
	else
		return;
}

template<class T> void CIDDataCollection<T>::SetTimestamp(string strID, unsigned int nElementIndex, float fTime){
	int nIDIndex = this->GetIndexOfID(strID);
	if (nIDIndex == -1)
		return;
	else if (nElementIndex < pIDData->at(nIDIndex).GetNumOfDataPayloads())
		pIDData->at(nIDIndex).SetTimestamp(nElementIndex, fTime);
}

template<class T> vector<T> CIDDataCollection<T>::GetData(string strID, unsigned int nIDDataIndex){
	int nIDIndex = this->GetIndexOfID(strID);
	if (nIDIndex == -1)
		return vector<T> (0, 0);
	else
	{
		if (nIDDataIndex >= pIDData->at(nIDIndex).GetNumOfDataPayloads())
			return vector<T> (0, 0);
		else
			return pIDData->at(nIDIndex).GetData(nIDDataIndex);
	}
}

template<class T> vector<T> CIDDataCollection<T>::GetData(unsigned int nIDIndex, unsigned int nIDDataIndex){
	if (nIDIndex >= pIDData->size())
		return vector<T> (0, 0);
	else
	{
		if (nIDDataIndex >= pIDData->at(nIDIndex).GetNumOfDataPayloads())
			return vector<T> (0, 0);
		else
			return pIDData->at(nIDIndex).GetData(nIDDataIndex);
	}
}

template<class T> string CIDDataCollection<T>::GetID(unsigned int nIDIndex){
	if (nIDIndex >= pIDData->size())
		return string("");
	else
		return pIDData->at(nIDIndex).GetID();
}

#endif /* IDDATACOLLECTION_H_ */
